require "../../spec_helper"
require "../../../src/output_builder/postman"
require "../../../src/models/endpoint"
require "../../../src/utils/utils"
require "json"

describe "OutputBuilderPostman" do
  it "print endpoints as Postman collection" do
    options = {
      "debug"   => YAML::Any.new(false),
      "verbose" => YAML::Any.new(false),
      "color"   => YAML::Any.new(false),
      "nolog"   => YAML::Any.new(false),
      "output"  => YAML::Any.new(""),
      "url"     => YAML::Any.new(""),
    }
    builder = OutputBuilderPostman.new(options)
    builder.set_io IO::Memory.new

    # Create endpoints with various HTTP methods and parameters
    endpoint1 = Endpoint.new("/pets/:petId", "GET")
    endpoint1.push_param(Param.new("petId", "123", "path"))
    endpoint1.push_param(Param.new("api_key", "key123", "header"))

    endpoint2 = Endpoint.new("/pets", "POST")
    endpoint2.push_param(Param.new("name", "Fluffy", "json"))
    endpoint2.push_param(Param.new("type", "cat", "json"))

    endpoint3 = Endpoint.new("/pets/:petId/photos", "POST")
    endpoint3.push_param(Param.new("petId", "123", "path"))
    endpoint3.push_param(Param.new("file", "photo.jpg", "form"))
    endpoint3.push_param(Param.new("description", "Pet photo", "form"))
    endpoint3.push_param(Param.new("session", "abc123", "cookie"))

    endpoint4 = Endpoint.new("/search", "GET")
    endpoint4.push_param(Param.new("q", "test", "query"))
    endpoint4.push_param(Param.new("limit", "10", "query"))

    endpoints = [endpoint1, endpoint2, endpoint3, endpoint4]
    builder.print(endpoints)
    output = builder.io.to_s

    # Verify output is valid Postman collection
    collection = JSON.parse(output)

    # Check collection info
    collection["info"]["name"].as_s.should eq("Generated by Noir")
    collection["info"]["schema"].as_s.should eq("https://schema.getpostman.com/json/collection/v2.1.0/collection.json")

    # Check items exist
    items = collection["item"].as_a
    items.size.should eq(4)

    # Check first item (GET with path param and header)
    item1 = items[0]
    item1["name"].as_s.should eq("GET /pets/:petId")
    item1["request"]["method"].as_s.should eq("GET")
    item1["request"]["url"]["path"].as_a.map(&.as_s).should eq(["pets", ":petId"])
    item1["request"]["url"]["variable"].as_a.size.should eq(1)
    item1["request"]["url"]["variable"][0]["key"].as_s.should eq("petId")
    item1["request"]["header"].as_a.size.should eq(1)
    item1["request"]["header"][0]["key"].as_s.should eq("api_key")

    # Check second item (POST with JSON body)
    item2 = items[1]
    item2["name"].as_s.should eq("POST /pets")
    item2["request"]["method"].as_s.should eq("POST")
    item2["request"]["body"]["mode"].as_s.should eq("raw")
    item2["request"]["body"]["options"]["raw"]["language"].as_s.should eq("json")

    # Verify JSON body content
    body_raw = item2["request"]["body"]["raw"].as_s
    body_json = JSON.parse(body_raw)
    body_json["name"].as_s.should eq("Fluffy")
    body_json["type"].as_s.should eq("cat")

    # Check Content-Type header is added for JSON body
    headers = item2["request"]["header"].as_a
    content_type_header = headers.find { |h| h["key"].as_s == "Content-Type" }
    content_type_header.should_not be_nil
    if content_type_header
      content_type_header["value"].as_s.should eq("application/json")
    end

    # Check third item (POST with form data and cookie)
    item3 = items[2]
    item3["name"].as_s.should eq("POST /pets/:petId/photos")
    item3["request"]["method"].as_s.should eq("POST")
    item3["request"]["body"]["mode"].as_s.should eq("urlencoded")
    item3["request"]["body"]["urlencoded"].as_a.size.should eq(2)

    # Check Cookie header
    cookie_header = item3["request"]["header"].as_a.find { |h| h["key"].as_s == "Cookie" }
    cookie_header.should_not be_nil
    if cookie_header
      cookie_header["value"].as_s.should contain("session=abc123")
    end

    # Check fourth item (GET with query params)
    item4 = items[3]
    item4["name"].as_s.should eq("GET /search")
    item4["request"]["method"].as_s.should eq("GET")
    item4["request"]["url"]["query"].as_a.size.should eq(2)
    query_keys = item4["request"]["url"]["query"].as_a.map(&.["key"].as_s)
    query_keys.should contain("q")
    query_keys.should contain("limit")

    # Check baseUrl variable
    collection["variable"].as_a.size.should eq(1)
    collection["variable"][0]["key"].as_s.should eq("baseUrl")
    collection["variable"][0]["value"].as_s.should eq("http://localhost")
  end

  it "uses custom URL when provided" do
    options = {
      "debug"   => YAML::Any.new(false),
      "verbose" => YAML::Any.new(false),
      "color"   => YAML::Any.new(false),
      "nolog"   => YAML::Any.new(false),
      "output"  => YAML::Any.new(""),
      "url"     => YAML::Any.new("https://api.example.com"),
    }
    builder = OutputBuilderPostman.new(options)
    builder.set_io IO::Memory.new

    endpoint = Endpoint.new("/test", "GET")
    builder.print([endpoint])
    output = builder.io.to_s

    collection = JSON.parse(output)
    collection["variable"][0]["value"].as_s.should eq("https://api.example.com")
  end
end
